/**
  ******************************************************************************
  * @file    flashdb_shell_commands.c
  * @author  Iron
  * @date    2021-01-01
  * @version v1.0
  * @brief   flashdb_shell_commands c file
  */

/** @addtogroup GROUP_TEMPLATE
  * @{
  */

/* Private includes ----------------------------------------------------------*/
#include "bsp.h"
#include <flashdb.h>
#include "shell.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static uint32_t boot_count = 0;
static time_t boot_time[10] = {0, 1, 2, 3};

/* default KV nodes */
static struct fdb_default_kv_node default_kv_table[] =
{
    {"username", "armink", 0}, /* string KV */
    {"password", "123456", 0}, /* string KV */
    {"boot_count", &boot_count, sizeof(boot_count)}, /* int type KV */
    {"boot_time", &boot_time, sizeof(boot_time)},    /* int array type KV */
};

/* KVDB object */

static struct fdb_kvdb kvdb = { 0 };

/* TSDB object */
struct fdb_tsdb tsdb = { 0 };

/* interrupt lockout posture.*/
static UINT tx_interrupt_control_posture;

/* Private function prototypes -----------------------------------------------*/
extern void kvdb_basic_sample(fdb_kvdb_t kvdb);
extern void kvdb_type_string_sample(fdb_kvdb_t kvdb);
extern void kvdb_type_blob_sample(fdb_kvdb_t kvdb);
extern void tsdb_sample(fdb_tsdb_t tsdb);

static void _fdb_lock(fdb_db_t db)
{
    /* Lockout interrupts */
    tx_interrupt_control_posture = tx_interrupt_control(TX_INT_DISABLE);
}

static void _fdb_unlock(fdb_db_t db)
{
    /* Restore previous interrupt lockout posture. */
    tx_interrupt_control(tx_interrupt_control_posture);
}

#ifdef FDB_USING_KVDB
int flashdb_kvdb_init(void)
{
    fdb_err_t result;
    struct fdb_default_kv default_kv;

    default_kv.kvs = default_kv_table;
    default_kv.num = sizeof(default_kv_table) / sizeof(default_kv_table[0]);

    /* set the lock and unlock function if you want */
    fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)_fdb_lock);
    fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)_fdb_unlock);

    /* Key-Value database initialization
     *
     *       &kvdb: database object
     *       "env": database name
     * "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
     *              Please change to YOUR partition name.
     * &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.
     *        NULL: The user data if you need, now is empty.
     */
    result = fdb_kvdb_init(&kvdb, "env", "fdb_kvdb1", &default_kv, NULL);

    if (result != FDB_NO_ERR)
    {
        return -1;
    }

    return 0;
}
#endif /* FDB_USING_KVDB */

#ifdef FDB_USING_TSDB
static fdb_time_t _fdb_get_time(void)
{
    /* Using the counts instead of timestamp.
     * Please change this function to return RTC time.
     */
    return tx_time_get();
}

int flashdb_tsdb_init(void)
{
    fdb_err_t result;

    /* set the lock and unlock function if you want */
    fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_LOCK, (void *)_fdb_lock);
    fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_SET_UNLOCK, (void *)_fdb_unlock);

    /* Time series database initialization
     *
     *       &tsdb: database object
     *       "log": database name
     * "fdb_tsdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
     *              Please change to YOUR partition name.
     *    get_time: The get current timestamp function.
     *         128: maximum length of each log
     *        NULL: The user data if you need, now is empty.
     */
    result = fdb_tsdb_init(&tsdb, "log", "fdb_tsdb1", get_time, 128, NULL);

    /* read last saved time for simulated timestamp */
//    fdb_tsdb_control(&tsdb, FDB_TSDB_CTRL_GET_LAST_TIME, &counts);

    if (result != FDB_NO_ERR)
    {
        return -1;
    }

    return 0;
}
#endif /* FDB_USING_TSDB */

int flashdb_init(void)
{
#ifdef FDB_USING_KVDB

    /* flashdb kvdb init */
    flashdb_kvdb_init();

#endif /* FDB_USING_KVDB */

#ifdef FDB_USING_TSDB

    /* flashdb tsb init */
    flashdb_tsdb_init();

#endif /* FDB_USING_TSDB */

    return 0;
}

/*----------------------------------------------------------------------------*/
char cmd_flashdb_kvdb_test(shell_context_t *shell, char *args)
{
#ifdef FDB_USING_KVDB

    /* run basic KV samples */
    kvdb_basic_sample(&kvdb);

    /* run string KV samples */
    kvdb_type_string_sample(&kvdb);

    /* run blob KV samples */
    kvdb_type_blob_sample(&kvdb);

#endif /* FDB_USING_KVDB */

#ifdef FDB_USING_TSDB

    /* run TSDB sample */
    tsdb_sample(&tsdb);

#endif /* FDB_USING_TSDB */

    return 0;
}

char cmd_flashdb_kvdb_list(shell_context_t *shell, char *args)
{
    fdb_kv_print(&kvdb);

    return NULL;
}

char cmd_flashdb_kvdb_clear(shell_context_t *shell, char *args)
{
    fdb_err_t result;

    result = fdb_kv_set_default(&kvdb);

    shell->shell_printf("done!(result=%d)\r\n", result);

    return NULL;
}

int fal_flash_stm32f0_get_runtime(int *error_cnt, int *read_cnt, int *write_cnt, int *erase_cnt);

char cmd_flashdb_flash_runtime(shell_context_t *shell, char *args)
{
    int error_cnt = 0;
    int read_cnt = 0;
    int write_cnt = 0;
    int erase_cnt = 0;

    fal_flash_stm32f0_get_runtime(&error_cnt, &read_cnt, &write_cnt, &erase_cnt);

    shell->shell_printf("error_cnt :%d, read_cnt: %d, write_cnt: %d, erase_cnt %d.\r\n", error_cnt, read_cnt, write_cnt, erase_cnt);

    return NULL;
}

char cmd_flashdb_kvdb_set(shell_context_t *shell, char *args)
{
    char *key, *value;
    fdb_err_t result = FDB_NO_ERR;

    key = args;
    value = strchr(args, ' ');

    if (key && value)
    {
        *value++ = '\0';

        result = fdb_kv_set(&kvdb, key, value);

        shell->shell_printf("kvdb set '%s' %s.(result=%d)\r\n", key, (result == FDB_NO_ERR) ? "ok" : "error", result);
    }
    else
    {
        shell->shell_printf("kvdb set args error.\r\n");
    }

    return NULL;
}

char cmd_flashdb_kvdb_get(shell_context_t *shell, char *args)
{
    char *key, *value;
    fdb_err_t result = FDB_NO_ERR;

    key = args;
 
    if (key)
    {
        value = fdb_kv_get(&kvdb, key);

        shell->shell_printf("kvdb get '%s' value: '%s'.(result=%d)\r\n", key, value, result);
    }
    else
    {
        shell->shell_printf("kvdb get args error.\r\n");
    }

    return NULL;
}


/**
  * @}
  */

/******************* (C)COPYRIGHT 2021 ***** END OF FILE *********************/
